package com.ymt.spi.webserver.tomcat.realm;

import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import com.ymt.spi.webserver.tomcat.realm.TenantPrincipal;

/**

 * @ClassName: SecurityFilter
 * @Description: 用户安全认证的过滤器
 * @author Johnny
 * @date 2015-12-24 下午2:15:21
 */
public class SecurityFilter implements Filter {
	
	/**
	 * logger.
	 */
	private Logger logger = Logger.getLogger(SecurityFilter.class.getName());

	private Set<String> prefixIignores = new HashSet<String>();
	
    /**
     * destroy.
     */
    public void destroy() {
    	
    }

    /**
     * @MethodName: doFilter
     * @Description: 检查用户是否已认证
     * @param request
     * @param response
     * @param filterChain
     * @throws IOException
     * @throws ServletException
     * @see javax.servlet.Filter#doFilter(javax.servlet.ServletRequest, javax.servlet.ServletResponse, javax.servlet.FilterChain)
     */
    public void doFilter(ServletRequest request, 
    		ServletResponse response,
            FilterChain filterChain) throws IOException, ServletException {

        HttpServletResponse res = (HttpServletResponse) response;
        HttpServletRequest req = (HttpServletRequest) request;

		String requestURI = req.getRequestURI();

		//判断是否不需要过滤
		if (canIgnore(requestURI)) {
			filterChain.doFilter(req, res);
			return;
		}

		//登录页面地址
        //String loginPath = req.getContextPath() + LoginConst.LOGIN_PAGE;
        String loginPath = req.getContextPath();

        if (logger.isLoggable(Level.FINEST)) {
        	logger.finest("doFilter request path=" + requestURI);
        	logger.finest("doFilter loginPath=" + loginPath);
        }

        //get session
        HttpSession session = req.getSession(true);
        
        //get login user
        TenantPrincipal principal = (TenantPrincipal) req.getUserPrincipal();
        //如果未认证，跳转到登录页面
        if (principal==null || principal.getName()==null || session==null) {
        	res.sendRedirect(loginPath);
        	logger.finest("doFilter principal is null");
        	return;
        }
        
        if (logger.isLoggable(Level.FINEST)) { 
        	logger.finest("doFilter principal.getName()=" + principal.getName());
        	logger.finest("doFilter principal.getDisplayName()=" + principal.getDisplayName());
        	logger.finest("doFilter principal.getPassword()=" + principal.getPassword());
        	logger.finest("doFilter principal.getTenantId()=" + principal.getTenantId());
        	logger.finest("doFilter principal.getJaasRoles()=" + principal.getJaasRoles());
        	logger.finest("doFilter principal.getBizRoles()=" + principal.getBizRoles());
        }
        
        try {
            
            /**
             * Judge JAAS Authentication Result
             */
            if (session.getAttribute(LoginConst.LOGINNAME)==null) {//用户已认证但session信息为空
            	//获取用户信息服务类
            	session.setAttribute(LoginConst.LOGINNAME, principal.getName());
            	session.setAttribute(LoginConst.DISPLAYNAME, principal.getDisplayName());
            	session.setAttribute(LoginConst.TENANTID, principal.getTenantId());
            	session.setAttribute(LoginConst.USERID, principal.getName());
            	session.setAttribute(LoginConst.LANG, LoginConst.LANG_ZH);
            	session.setAttribute(LoginConst.ROLES, toJSONString(principal.getBizRoles()));
            	//TODO profile
            }
            
        } catch (Exception ex) {
        	//如果认证发生错误，返回登录页面
            ex.printStackTrace(System.out);
            logger.log(Level.WARNING, "doFilter exception:" + ex.getMessage(), ex);
            res.sendRedirect(loginPath);
        }
        
        //继续运行其他过滤器
        filterChain.doFilter(request, response);

    }

    /**
     * init.
     * @param config
     * 
     */
    public void init(FilterConfig config) {
		String cp = config.getServletContext().getContextPath();
		String ignoresParam = config.getInitParameter("ignores");
		if (ignoresParam!=null && ignoresParam.length()>0) {
			String[] ignoreArray = ignoresParam.split(",");
			for (String s : ignoreArray) {
				prefixIignores.add(cp + s.replace(" ", ""));
			}
		}
    }
    
    private String toJSONString(List<String> list) {
    	StringBuilder sb = new StringBuilder("[");
    	if (list!=null && list.size()>0) {
    		for (String s : list) {
    			if (sb.length()>1) sb.append(", ");
    			sb.append("\"");
    			sb.append(s);
    			sb.append("\"");
    		}
    	}
    	sb.append("]");
    	return sb.toString();
    }

	private boolean canIgnore(String url) {
    	if (!prefixIignores.isEmpty()) {
			for (String ignore : prefixIignores) {
				if (url.startsWith(ignore)) {
					return true;
				}
			}
		}
		return false;
	}
    
}
